package com.qinglei.recoup.system.service.impl;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qinglei.recoup.common.domain.CommonConstant;
import com.qinglei.recoup.common.domain.CommonRes;
import com.qinglei.recoup.common.exception.RedisConnectException;
import com.qinglei.recoup.common.service.RedisService;
import com.qinglei.recoup.common.tenant.TenantContextHolder;
import com.qinglei.recoup.common.utils.DateTimeUtils;
import com.qinglei.recoup.common.utils.DateUtil;
import com.qinglei.recoup.common.utils.JsonUtils;
import com.qinglei.recoup.common.utils.RecoupUtil;
import com.qinglei.recoup.system.dao.SystemConfigMapper;
import com.qinglei.recoup.system.domain.*;
import com.qinglei.recoup.system.pojo.AbnormalTimeVO;
import com.qinglei.recoup.system.pojo.TimePeriodParam;
import com.qinglei.recoup.system.pojo.TourTimeVO;
import com.qinglei.recoup.system.service.*;
import lombok.extern.slf4j.Slf4j;
import net.sf.json.JSONObject;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.LocalTime;
import java.util.ArrayList;
import java.util.List;

/**
 * @author syp
 */
@Service
@Slf4j
public class SystemConfigServiceImpl extends ServiceImpl<SystemConfigMapper, SystemConfig> implements SystemConfigService {

    @Autowired
    private TenantService tenantService;
    @Autowired
    private RedisService redisService;

    @Resource
    private VitalSignsAlarmService vitalSignsAlarmService;

    @Resource
    private RealTimeMonitoringService realTimeMonitoringService;

    @Resource
    private HealthBigDataService healthBigDataService;


    @Value("${recoup.tenant.default-system-configs}")
    private String defaultSystemConfigs;


    public static final int OUT_BED_TIMEOUT_DEF = 300;
    public static final int AKE_EVENT_TIMEOUT_DEF = 1800;

//    @Override
//    public int getOutBedTimeout() {
//        return getSecondVal(TYPE_OUT_BED_TIMEOUT, OUT_BED_TIMEOUT_DEF);
//    }

    //    @Override
    private int getTakeEventTimeout() {
        return getSecondVal(TYPE_TAKE_EVENT_TIMEOUT, AKE_EVENT_TIMEOUT_DEF);
    }

    /**
     * 获取巡视时间列表
     *
     * @return
     */
    @Override
    public List<TourTimeVO> getTourTimeList() {
        List<TourTimeVO> tourTimeVOList = new ArrayList<>();
        List<SystemConfig> configList = baseMapper.selectList(Wrappers.<SystemConfig>lambdaQuery().eq(SystemConfig::getType, TYPE_TOUR_TIME));
        configList.forEach(item -> {
            try {
                TourTimeVO tourTimeVO = JsonUtils.jsonToBean(item.getValue(), TourTimeVO.class);
                if (tourTimeVO != null) {
                    tourTimeVO.setId(item.getId());
                    tourTimeVO.setTenantId(item.getTenantId());
                    tourTimeVOList.add(tourTimeVO);
                }
            } catch (Exception e) {
                log.error("getTourTimeList error", e);
            }
        });
        return tourTimeVOList;
    }

    /**
     * 查询要录入的时间段是否与已存在的时间段有重叠时间段
     *
     * @param monitorTimeQO
     * @return
     */
    @Override
    public boolean overlap(TimePeriodParam monitorTimeQO, Integer type) {
        // 传入时间段
        TimePeriodParam timePeriodIn = new TimePeriodParam(monitorTimeQO.getStartTime(), monitorTimeQO.getEndTime());

        // 查询监测时间段
        List<SystemConfig> systemConfigs = baseMapper.selectList(Wrappers.<SystemConfig>lambdaQuery().eq(SystemConfig::getType, type));

        // 遍历比较时间是否有重叠
        for (SystemConfig sc : systemConfigs) {
            TourTimeVO tourTimeVO = JsonUtils.jsonToBean(sc.getValue(), TourTimeVO.class);
            TimePeriodParam timePeriodCur = new TimePeriodParam(tourTimeVO.getStartTime(), tourTimeVO.getEndTime());
            boolean res = DateTimeUtils.checkTimeOverlap(timePeriodIn, timePeriodCur);
            if (res) {
                return true;
            }
        }
        return false;
    }

    @Override
    public void loadTakeEventTimeoutRedisCache() throws RedisConnectException {
        List<Tenant> list = tenantService.list();
        Integer bakTenantId = TenantContextHolder.getTenantId();
        for (Tenant tenant : list) {
            TenantContextHolder.setTenantId(tenant.getId());
            int time = getSecondVal(TYPE_TAKE_EVENT_TIMEOUT, AKE_EVENT_TIMEOUT_DEF);
            this.setTakeEventTimeoutRedisCache(tenant.getId(), time);
            List<RealTimeMonitoring> list2 = realTimeMonitoringService.list(Wrappers.<RealTimeMonitoring>lambdaQuery().eq(RealTimeMonitoring::getTenantId, tenant.getId()));
            if(list2 != null && !list2.isEmpty()){
                list2.forEach(f->{
                    f.setCreateTime(null);
                    f.setModifyTime(null);
                });
                String s1 = JsonUtils.objectToJson(list2);
                redisService.set("RealTimeMonitoring-"+list2.get(0).getTenantId(),s1);
            }
        }
        TenantContextHolder.setTenantId(bakTenantId);
        List<VitalSignsAlarm> list1 = vitalSignsAlarmService.list();
        if (list1 != null && !list1.isEmpty() ) {
            list1.forEach(f->{
                f.setCreateTime(null);
                f.setModifyTime(null);
                String s = JsonUtils.objectToJson(f);
                try {
                    redisService.set("VitalSignsAlarm-"+f.getTenantId()+"-"+f.getSignType(),s);
                } catch (RedisConnectException e) {
                    e.printStackTrace();
                }
            });
        }


        List<HealthBigData> list3 = healthBigDataService.list();
        if (list3 != null && !list3.isEmpty() ) {
            list3.forEach(f->{
                String s = JsonUtils.objectToJson(f);
                try {
                    redisService.set("HealthBigData-"+f.getTenantId()+"-"+f.getBigDataType(),s);
                } catch (RedisConnectException e) {
                    e.printStackTrace();
                }
            });
        }
    }

    @Override
    public void setTakeEventTimeoutRedisCache(Integer tenantId, Integer time) throws RedisConnectException {
        redisService.hset(CommonConstant.TAKE_EVENT_TIMEOUT_CACHE_PREFIX, String.valueOf(tenantId), String.valueOf(time));
    }

    @Override
    public Integer getTakeEventTimeoutRedisCache(Integer tenantId) {
        Integer ret = AKE_EVENT_TIMEOUT_DEF;
        try {
            String val = redisService.hget(CommonConstant.TAKE_EVENT_TIMEOUT_CACHE_PREFIX, String.valueOf(tenantId));
            if (val != null) {
                ret = Integer.valueOf(val);
            }
        } catch (Exception e) {
            log.warn("getTakeEventTimeoutRedisCache error", e);
        }
        return ret;
    }

    /**
     * 获取默认离床时间阀值
     *
     * @return
     */
    @Override
    public String getDefaultOutBedTimeout() {
        List<SystemConfig> systemConfigs = JsonUtils.jsonToList(defaultSystemConfigs, SystemConfig.class);
        for (SystemConfig systemConfig : systemConfigs) {
            if (systemConfig.getType() == SystemConfigService.TYPE_OUT_BED_TIMEOUT) {
                return JsonUtils.jsonToBean(systemConfig.getValue(),String.class);
            }
        }
//        SystemConfig systemConfig = getBaseMapper().selectOne(Wrappers.<SystemConfig>lambdaQuery().eq(SystemConfig::getType, 3));
//        if (systemConfig != null){
//            return JsonUtils.jsonToBean(systemConfig.getValue(),String.class);
//        }
        return null;
    }

    /**
     * 获取默认监控时间
     *
     * @return
     */
    @Override
    public List<TimePeriodParam> getDefaultMonitorTime() {
        List<TimePeriodParam> timePeriodParams = new ArrayList<>();
        List<SystemConfig> systemConfigs = JsonUtils.jsonToList(defaultSystemConfigs, SystemConfig.class);
        for (SystemConfig systemConfig : systemConfigs) {
            if (systemConfig.getType() == SystemConfigService.TYPE_DEF_MONITOR_TIME) {
                //TimePeriodParam timePeriodParam = JsonUtils.jsonToBean(systemConfig.getValue(), TimePeriodParam.class);
                TimePeriodParam timePeriodParam = (TimePeriodParam) JSONObject.toBean(JSONObject.fromObject(systemConfig.getValue()), TimePeriodParam.class);
                timePeriodParams.add(timePeriodParam);
            }
        }
//        List<SystemConfig> systemConfigs = getBaseMapper().selectList(Wrappers.<SystemConfig>lambdaQuery().eq(SystemConfig::getType, SystemConfigService.TYPE_DEF_MONITOR_TIME));
//        for (SystemConfig sc:systemConfigs) {
//            TimePeriodParam monitorTimeQO = JsonUtils.jsonToBean(sc.getValue(), TimePeriodParam.class);
//            monitorTimeQOS.add(monitorTimeQO);
//        }
        return timePeriodParams;
    }

    /**
     * 获取秒值
     *
     * @param type
     * @param defVal
     * @return
     */
    private int getSecondVal(int type, int defVal) {
        int secondVal = defVal;
        SystemConfig one = this.getOne(Wrappers.<SystemConfig>lambdaQuery().eq(SystemConfig::getType, type));
        if (one != null) {
            try {
                String value = JsonUtils.jsonToBean(one.getValue(), String.class);
                secondVal = DateUtil.str2Second(value, defVal);
            } catch (Exception e) {
                log.warn("getOutBedTimeout 转换时间错误", e);
            }
        }
        return secondVal;
    }

    @Override
    public CommonRes getAbnormalTime() {
        SystemConfig systemConfig = baseMapper.selectOne(Wrappers.<SystemConfig>lambdaQuery().eq(SystemConfig::getType, TYPE_OUT_BED_TIMEOUT));
        AbnormalTimeVO abnormalTimeVO = new AbnormalTimeVO();
        if (systemConfig != null) {
            BeanUtils.copyProperties(systemConfig, abnormalTimeVO);
        }
        return CommonRes.ok(abnormalTimeVO);
    }

    @Override
    public CommonRes uptAbnormalTime(AbnormalTimeVO abnormalTimeVO) throws RedisConnectException {
        SystemConfig systemConfig = new SystemConfig();
        systemConfig.setType(TYPE_OUT_BED_TIMEOUT);
        BeanUtils.copyProperties(abnormalTimeVO, systemConfig);
        systemConfig.setValue(JsonUtils.objectToJson(abnormalTimeVO.getValue()));
        if (abnormalTimeVO.getId() != null) {
            int updateById = baseMapper.updateById(systemConfig);
            if (updateById > 0) {
                return CommonRes.ok();
            }
            return CommonRes.failed("修改失败");
        } else {
            int insert = baseMapper.insert(systemConfig);
            if (insert > 0) {
                return CommonRes.ok();
            }
            return CommonRes.failed("添加失败");
        }
    }

    @Override
    public CommonRes uptNurseAbnormalTime(AbnormalTimeVO abnormalTimeVO) throws RedisConnectException {
        SystemConfig systemConfig = new SystemConfig();
        systemConfig.setType(TYPE_TAKE_EVENT_TIMEOUT);
        BeanUtils.copyProperties(abnormalTimeVO, systemConfig);
        systemConfig.setValue(JsonUtils.objectToJson(abnormalTimeVO.getValue()));
        systemConfig.setTenantId(RecoupUtil.getCurrentUser().getTenantId());
        LocalTime time = LocalTime.parse(abnormalTimeVO.getValue());
        Integer secondVal = time.toSecondOfDay();
        if (systemConfig.getId() != null) {
            int updateById = getBaseMapper().updateById(systemConfig);
            if (updateById > 0) {
                this.setTakeEventTimeoutRedisCache(systemConfig.getTenantId(), secondVal);
                return CommonRes.ok();
            }
            return CommonRes.failed("修改失败");
        } else {
            int insert = baseMapper.insert(systemConfig);
            if (insert > 0) {
                this.setTakeEventTimeoutRedisCache(systemConfig.getTenantId(), secondVal);
                return CommonRes.ok();
            }
            return CommonRes.failed("添加失败");
        }

    }

    @Override
    public CommonRes getNurseAbnormalTime() {
        SystemConfig systemConfig = baseMapper.selectOne(Wrappers.<SystemConfig>lambdaQuery().eq(SystemConfig::getType, TYPE_TAKE_EVENT_TIMEOUT));
        AbnormalTimeVO abnormalTimeVO = new AbnormalTimeVO();
        if (systemConfig != null) {
            BeanUtils.copyProperties(systemConfig, abnormalTimeVO);
        }
        return CommonRes.ok(abnormalTimeVO);
    }
}
